package edu.upol.paradise.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import edu.upol.paradise.compiler.CompilerError;
import edu.upol.paradise.compiler.types.ParadiseObject;
import edu.upol.paradise.compiler.types.ParadisePair;
import edu.upol.paradise.compiler.types.ParadiseSymbol;

public class VariableClosureStack {
	
	private Map<ParadisePair, Set<String>>
		markedLines = new HashMap<ParadisePair, Set<String>>();
	private List<Set<String>> layers
		= new ArrayList<Set<String>>();
	private List<Set<String>> variablesProvided
		= new ArrayList<Set<String>>();
	
	public VariableClosureStack(){
	}
	
	public void push(){
		layers.add(new HashSet<String>());
		variablesProvided.add(new HashSet<String>());
	}
	
	public void addHeader(ParadiseObject definitions) throws CompilerError{
		if (definitions instanceof ParadiseSymbol)
			addHeaderSymbol(((ParadiseSymbol)definitions).toString());
		else {
			List<ParadiseSymbol> plist = Utils.pair2alist((ParadisePair) definitions);
			for (ParadiseSymbol ss : plist)
				addHeaderSymbol(ss.toString());
		}
	}
	
	private void addHeaderSymbol(String symbol) {
		variablesProvided.get(variablesProvided.size()-1).add(symbol);
	}

	public void addSymbol(String symbol){
		layers.get(layers.size()-1).add(symbol);
	}
	
	public void pop(ParadisePair marker){
		HashSet<String> sset = new HashSet<String>();
		for (int i=0; i<variablesProvided.size()-1; i++)
			sset.addAll(variablesProvided.get(i));
		HashSet<String> excludeSet = Utils.setBoth(sset, layers.get(layers.size()-1));
		layers.remove(layers.size()-1);
		variablesProvided.remove(variablesProvided.size()-1);
		markedLines.put(marker, excludeSet);
	}

	public Set<String> get(ParadiseObject v) {
		return markedLines.get(v);
	}
	
}
